home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / ODMemMgr / Sources / MemoryHe.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-03  |  34.3 KB  |  1,196 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        MemoryHe.cpp
  3.  
  4.     Contains:    MemoryHeap class implementation
  5.  
  6.     Owned by:    Michael Burbidge, Jens Alfke
  7.     Owned by:    Jens Alfke
  8.  
  9.     Copyright:    © 1993 - 1995-96 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.                   3/5/96    TWB        Comment out unused arguments to suppress warnings. 
  13.                  2/13/96    srf        SIZE_T -> size_t
  14.             
  15.         <16>    10/24/95    jpa        1293441: Added slush-fund.
  16.         <15>      8/4/95    DM        Leak detection [1267956]
  17.         <14>      6/7/95    jpa        IsValidBlock calls hooks to check for
  18.                                     prefix/suffix validity. [1256829]
  19.         <13>      5/5/95    TJ        jpa: Don't call hooks in nondebug build.
  20.         <12>      5/4/95    jpa        Support for finding largest free block
  21.                                     [1235657] and validating memory ranges
  22.                                     [1246077]
  23.         <11>    12/20/94    jpa        Fixed constructor typo that turned on
  24.                                     fZapOnFree.
  25.         <10>     12/5/94    jpa        Nuked errant pragma lib_export's. [1195676]
  26.          <9>    10/24/94    jpa        Constness [1194286].
  27.          <8>     9/29/94    RA        1189812: Mods for 68K build.
  28.          <7>     9/14/94    jpa        Eliminated dependencies on rest of OpenDoc.
  29.                                     Added support for getting the heap of a
  30.                                     block. [1186692]
  31.          <6>     8/17/94    jpa        Added support for walking heaps [1179567].
  32.          <5>      8/8/94    jpa        Zap old block after reallocate.
  33.          <4>      8/2/94    jpa        Fixed bug in BlockSize (wasn't calling
  34.                                     hooks when it should)
  35.          <3>     6/18/94    MB        More initial SOM deployment
  36.          <2>     6/10/94    MB        Make it build
  37.          <1>      6/9/94    MB        first checked in
  38.          <3>     5/26/94    MB        #1162181: Fixed MMM integration bug
  39.          <2>      5/9/94    MB        #1162181: Changes necessary to install MMM.
  40.          <1>     4/29/94    MB        first checked in
  41.     To Do:
  42.     In Progress:
  43.         
  44. */
  45.  
  46. #ifndef _PLATFMEM_
  47. #include "PlatfMem.h"
  48. #endif
  49.  
  50. #ifndef _MEMORYHE_
  51. #include "MemoryHe.h"
  52. #endif
  53.  
  54. #ifndef _MEMHOOKS_
  55. #include "MemHooks.h"
  56. #endif
  57.  
  58. #ifndef __MEMORY__
  59. #include <Memory.h>
  60. #endif
  61.  
  62. #ifndef __STDIO__
  63. #include <stdio.h>
  64. #endif
  65.  
  66.  
  67. //========================================================================================
  68. // CLASS ODMemoryHook (MM_DEBUG only)
  69. //========================================================================================
  70.  
  71. #if MM_DEBUG
  72. //----------------------------------------------------------------------------------------
  73. // ODMemoryHook::ODMemoryHook
  74. //----------------------------------------------------------------------------------------
  75. #pragma segment HeapSeg
  76.  
  77. ODMemoryHook::ODMemoryHook()
  78. {
  79.     fNextHook = fPreviousHook = this;
  80. }
  81. #endif
  82.  
  83. #if MM_DEBUG
  84. //----------------------------------------------------------------------------------------
  85. // ODMemoryHook::~ODMemoryHook
  86. //----------------------------------------------------------------------------------------
  87. #pragma segment HeapSeg
  88.  
  89. ODMemoryHook::~ODMemoryHook()
  90. {
  91. }
  92. #endif
  93.  
  94. #if MM_DEBUG
  95. //----------------------------------------------------------------------------------------
  96. // ODMemoryHook::operator new
  97. //----------------------------------------------------------------------------------------
  98. #pragma segment HeapSeg
  99.  
  100. void* ODMemoryHook::operator new(size_t size, MMHeapLocation src)
  101. {
  102.     return PlatformAllocateBlock(size, src);
  103. }
  104. #endif
  105.  
  106. #if MM_DEBUG
  107. //----------------------------------------------------------------------------------------
  108. // ODMemoryHook::operator delete
  109. //----------------------------------------------------------------------------------------
  110. #pragma segment HeapSeg
  111.  
  112. void ODMemoryHook::operator delete(void* ptr)
  113. {
  114.         PlatformFreeBlock(ptr);
  115. }
  116. #endif
  117.  
  118. #if MM_DEBUG
  119. //----------------------------------------------------------------------------------------
  120. // ODMemoryHook::GetHeaderSize
  121. //----------------------------------------------------------------------------------------
  122. #pragma segment HeapSeg
  123.  
  124. ODBlockSize ODMemoryHook::GetHeaderSize()
  125. {
  126.     return 0;
  127. }
  128. #endif
  129.  
  130. #if MM_DEBUG
  131. //----------------------------------------------------------------------------------------
  132. // ODMemoryHook::AboutToAllocate
  133. //----------------------------------------------------------------------------------------
  134. #pragma segment HeapSeg
  135.  
  136. ODBlockSize ODMemoryHook::AboutToAllocate(ODBlockSize size) const
  137. {
  138.     return size;
  139. }
  140. #endif
  141.  
  142. #if MM_DEBUG
  143. //----------------------------------------------------------------------------------------
  144. // ODMemoryHook::DidAllocate
  145. //----------------------------------------------------------------------------------------
  146. #pragma segment HeapSeg
  147.  
  148. void *ODMemoryHook::DidAllocate(void* blk, ODBlockSize)
  149. {
  150.     return blk;
  151. }
  152. #endif
  153.  
  154. #if MM_DEBUG
  155. //----------------------------------------------------------------------------------------
  156. // ODMemoryHook::AboutToBlockSize
  157. //----------------------------------------------------------------------------------------
  158. #pragma segment HeapSeg
  159.  
  160. const void *ODMemoryHook::AboutToBlockSize(const void* blk)
  161. {
  162.     return blk;
  163. }
  164. #endif
  165.  
  166. #if MM_DEBUG
  167. //----------------------------------------------------------------------------------------
  168. // ODMemoryHook::AboutToFree
  169. //----------------------------------------------------------------------------------------
  170. #pragma segment HeapSeg
  171.  
  172. void *ODMemoryHook::AboutToFree(void* blk)
  173. {
  174.     return blk;
  175. }
  176. #endif
  177.  
  178. #if MM_DEBUG
  179. //----------------------------------------------------------------------------------------
  180. // ODMemoryHook::AboutToRealloc
  181. //----------------------------------------------------------------------------------------
  182. #pragma segment HeapSeg
  183.  
  184. void ODMemoryHook::AboutToRealloc(void* &, ODBlockSize &)
  185. {
  186. }
  187. #endif
  188.  
  189. #if MM_DEBUG
  190. //----------------------------------------------------------------------------------------
  191. // ODMemoryHook::DidRealloc
  192. //----------------------------------------------------------------------------------------
  193. #pragma segment HeapSeg
  194.  
  195. void *ODMemoryHook::DidRealloc(void */*oldBlk*/, void *blk, ODBlockSize)
  196. {
  197.     return blk;
  198. }
  199. #endif
  200.  
  201. #if MM_DEBUG
  202. //----------------------------------------------------------------------------------------
  203. // ODMemoryHook::AboutToReset
  204. //----------------------------------------------------------------------------------------
  205. #pragma segment HeapSeg
  206.  
  207. void ODMemoryHook::AboutToReset()
  208. {
  209. }
  210. #endif
  211.  
  212. #if MM_DEBUG
  213. //----------------------------------------------------------------------------------------
  214. // ODMemoryHook::Comment
  215. //----------------------------------------------------------------------------------------
  216. #pragma segment HeapSeg
  217.  
  218. void ODMemoryHook::Comment(const char*)
  219. {
  220. }
  221. #endif
  222.  
  223. #if MM_DEBUG
  224. //----------------------------------------------------------------------------------------
  225. // ODMemoryHook::GetType
  226. //----------------------------------------------------------------------------------------
  227. #pragma segment HeapSeg
  228.  
  229. long ODMemoryHook::GetType() const
  230. {
  231.     return ODMemoryHook::kNoType;
  232. }
  233. #endif
  234.  
  235.  
  236. //========================================================================================
  237. // CLASS MemoryHookList (MM_DEBUG only)
  238. //========================================================================================
  239.  
  240. #if MM_DEBUG
  241. //----------------------------------------------------------------------------------------
  242. // MemoryHookList::MemoryHookList
  243. //----------------------------------------------------------------------------------------
  244. #pragma segment HeapSeg
  245.  
  246. MemoryHookList::MemoryHookList()
  247. {
  248. }
  249. #endif
  250.  
  251. #if MM_DEBUG
  252. //----------------------------------------------------------------------------------------
  253. // MemoryHookList::Add
  254. //----------------------------------------------------------------------------------------
  255. #pragma segment HeapSeg
  256.  
  257. void MemoryHookList::Add(ODMemoryHook* aMemoryHook)
  258. {
  259.     // Add at the fEnd of the list by adding after the last hook in the list.
  260.     
  261.     ODMemoryHook* afterHook = fHead.fPreviousHook;
  262.     
  263.     aMemoryHook->fNextHook = afterHook->fNextHook;
  264.     afterHook->fNextHook->fPreviousHook = aMemoryHook;
  265.     aMemoryHook->fPreviousHook = afterHook;
  266.     afterHook->fNextHook = aMemoryHook;
  267. }
  268. #endif
  269.  
  270. #if MM_DEBUG
  271. //----------------------------------------------------------------------------------------
  272. // MemoryHookList::Remove
  273. //----------------------------------------------------------------------------------------
  274. #pragma segment HeapSeg
  275.  
  276. void MemoryHookList::Remove(ODMemoryHook* aMemoryHook)
  277. {
  278.     aMemoryHook->fPreviousHook->fNextHook = aMemoryHook->fNextHook;
  279.     aMemoryHook->fNextHook->fPreviousHook = aMemoryHook->fPreviousHook;
  280. }
  281. #endif
  282.  
  283. #if MM_DEBUG
  284. //----------------------------------------------------------------------------------------
  285. // MemoryHookList::First
  286. //----------------------------------------------------------------------------------------
  287. #pragma segment HeapSeg
  288.  
  289. ODMemoryHook* MemoryHookList::First() const
  290. {
  291.     ODMemoryHook *h = fHead.fNextHook;
  292.     return h != &fHead ? h : NULL;
  293. }
  294. #endif
  295.  
  296. #if MM_DEBUG
  297. //----------------------------------------------------------------------------------------
  298. // MemoryHookList::Next
  299. //----------------------------------------------------------------------------------------
  300. #pragma segment HeapSeg
  301.  
  302. ODMemoryHook* MemoryHookList::After( ODMemoryHook *h ) const
  303. {
  304.     h = h->fNextHook;
  305.     return h != &fHead ? h : NULL;
  306. }
  307. #endif
  308.  
  309. #if MM_DEBUG
  310. //----------------------------------------------------------------------------------------
  311. // MemoryHookList::Previous
  312. //----------------------------------------------------------------------------------------
  313. #pragma segment HeapSeg
  314.  
  315. ODMemoryHook* MemoryHookList::Before( ODMemoryHook *h ) const
  316. {
  317.     h = h->fPreviousHook;
  318.     return h != &fHead ? h : NULL;
  319. }
  320. #endif
  321.  
  322. #if MM_DEBUG
  323. //----------------------------------------------------------------------------------------
  324. // MemoryHookList::Last
  325. //----------------------------------------------------------------------------------------
  326. #pragma segment HeapSeg
  327.  
  328. ODMemoryHook* MemoryHookList::Last() const
  329. {
  330.     ODMemoryHook *h = fHead.fPreviousHook;
  331.     return h != &fHead ? h : NULL;
  332. }
  333. #endif
  334.  
  335. #if MM_DEBUG
  336. //----------------------------------------------------------------------------------------
  337. // MemoryHookList::~MemoryHookList
  338. //----------------------------------------------------------------------------------------
  339. #pragma segment HeapSeg
  340.  
  341. MemoryHookList::~MemoryHookList()
  342. {
  343.     for (ODMemoryHook *hook = First(); hook != NULL; hook = First())
  344.     {
  345.         Remove(hook);
  346.         delete hook;
  347.     }
  348. }
  349. #endif
  350.  
  351.  
  352. //========================================================================================
  353. // CLASS MemoryHeap
  354. //========================================================================================
  355.  
  356. const char *MemoryHeap::kDefaultDescription = "Give this MemoryHeap a description";
  357. const char *MemoryHeap::kDeadHeapDescription = "Dead heap, dead heap, dead heap!";
  358. MemoryHeap *MemoryHeap::fHeapList;                                // Don't initialize!
  359.  
  360. //----------------------------------------------------------------------------------------
  361. // MemoryHeap::ValidateMagicNumber  (MM_DEBUG only)
  362. //----------------------------------------------------------------------------------------
  363.  
  364. #if MM_DEBUG
  365.  
  366.     #pragma segment HeapSeg
  367.     MMBoolean MemoryHeap::ValidateMagicNumber( ) const /* Adkins -- made ValidateMagicNumber( ) const */
  368.     {
  369.         if( fMagicNumber != kMagicNumber ) {
  370.             MM_WARN("Invalid magic number for heap %d -- is this a valid heap?",this);
  371.             return kMMFalse;
  372.         } else
  373.             return kMMTrue;
  374.     }
  375.     
  376. #endif
  377.  
  378. //----------------------------------------------------------------------------------------
  379. // MemoryHeap::GetFirstHeap
  380. //----------------------------------------------------------------------------------------
  381. #pragma segment HeapSeg
  382.  
  383. MemoryHeap *MemoryHeap::GetFirstHeap()
  384. {
  385.     return fHeapList;
  386. }
  387.  
  388. //----------------------------------------------------------------------------------------
  389. // MemoryHeap::Allocate
  390. //----------------------------------------------------------------------------------------
  391. #pragma segment HeapSeg
  392.  
  393. void *MemoryHeap::Allocate(ODBlockSize size)
  394. {
  395.     this->ValidateMagicNumber();
  396.  
  397.     ODBlockSize originalSize = size;
  398. #if MM_DEBUG
  399.     size = this->CallAboutToAllocateHooks(size);
  400. #endif
  401.  
  402.     ODBlockSize allocatedSize;
  403.     void *blk = this->DoAllocate( size, allocatedSize);
  404.     
  405.     if( blk==kMMNULL && originalSize<=fSlushFundAllocSizeLimit ) {
  406.         // Free slush fund. Do not try again, let the caller know it ran out of memory.
  407.         // But a little memory will now be available to make cleanup possible.
  408.         MM_WARN( this->GetSlushFundSize()>0 ?"Out of memory. Freed slush fund."
  409.                                             :"Out of memory, no slush fund. Oh, dear." );
  410.         this->FreeSlushFund();
  411.     }
  412.     
  413.     if (blk != kMMNULL)
  414.     {
  415.         if (fZapOnAllocate)
  416.             PlatformZapMem(blk,allocatedSize,0xBBBBBBBB);
  417.         fBytesAllocated += allocatedSize;
  418.         fNumberAllocatedBlocks++;
  419.     }
  420.  
  421. #if MM_DEBUG
  422.     blk = this->CallDidAllocateHooks(blk, size);
  423. #endif
  424.  
  425.     return blk;
  426. }
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // MemoryHeap::BlockSize
  430. //----------------------------------------------------------------------------------------
  431. #pragma segment HeapSeg
  432.  
  433. ODBlockSize MemoryHeap::BlockSize(const void *blk) const
  434. {
  435.     this->ValidateMagicNumber();
  436.  
  437.     if (blk == NULL)
  438.         return 0;
  439.         
  440. #if MM_DEBUG
  441.     if (fAutoValidation)
  442.         this->ValidateAndReport((void*)blk);
  443.         
  444.     blk = ((MemoryHeap *) this)->CallAboutToBlockSizeHooks((void*)blk);
  445. #endif
  446.  
  447.     ODBlockSize size = this->DoBlockSize((void*)blk);
  448.  
  449. #if MM_DEBUG
  450.     size -= this->CallAboutToAllocateHooks(0);        // Subtract hook pad size
  451. #endif
  452.     return size;
  453. }
  454.  
  455. //----------------------------------------------------------------------------------------
  456. // MemoryHeap::BytesAllocated
  457. //----------------------------------------------------------------------------------------
  458. #pragma segment HeapSeg
  459.  
  460. unsigned long MemoryHeap::BytesAllocated() const
  461. {
  462.     this->ValidateMagicNumber();
  463.  
  464.     return fBytesAllocated;
  465. }
  466.  
  467. //----------------------------------------------------------------------------------------
  468. // MemoryHeap::Free
  469. //----------------------------------------------------------------------------------------
  470. #pragma segment HeapSeg
  471.  
  472. void MemoryHeap::Free(void* blk)
  473. {
  474.     this->ValidateMagicNumber();
  475.  
  476.     if (blk == NULL)
  477.         return;
  478.         
  479. #if MM_DEBUG
  480.     if (fAutoValidation)
  481.         this->ValidateAndReport(blk);
  482.         
  483.     blk = this->CallAboutToFreeHooks(blk);
  484. #endif
  485.     
  486.     ODBlockSize allocatedSize = (ODBlockSize) this->DoBlockSize(blk);
  487.     
  488.     if (fZapOnFree)
  489.             PlatformZapMem(blk,allocatedSize,0xDDDDDDDD);
  490.  
  491.     this->DoFree(blk);
  492.  
  493.     fBytesAllocated -= allocatedSize;
  494.     fNumberAllocatedBlocks--;
  495. }
  496.  
  497. //----------------------------------------------------------------------------------------
  498. // MemoryHeap::LargestFreeBlock
  499. //----------------------------------------------------------------------------------------
  500. #pragma segment HeapSeg
  501.  
  502. unsigned long MemoryHeap::LargestFreeBlock( ) const
  503. {
  504.     long result = this->DoLargestFreeBlock();
  505. #if MM_DEBUG
  506.     result -= this->CallAboutToAllocateHooks(0);
  507. #endif
  508.     return result>0 ?result :0;
  509. }
  510.  
  511. #if MM_DEBUG
  512. //----------------------------------------------------------------------------------------
  513. // MemoryHeap::GetAutoValidation (MM_DEBUG only)
  514. //----------------------------------------------------------------------------------------
  515. #pragma segment HeapSeg
  516.  
  517. Boolean MemoryHeap::GetAutoValidation() const
  518. {
  519.     this->ValidateMagicNumber();
  520.  
  521.     return fAutoValidation;
  522. }
  523. #endif
  524.  
  525. //----------------------------------------------------------------------------------------
  526. // MemoryHeap::GetDescription
  527. //----------------------------------------------------------------------------------------
  528. #pragma segment HeapSeg
  529.  
  530. const char *MemoryHeap::GetDescription() const
  531. {
  532.     this->ValidateMagicNumber();
  533.  
  534.     return fDescription;
  535. }
  536.  
  537. //----------------------------------------------------------------------------------------
  538. // MemoryHeap::GetNextHeap
  539. //----------------------------------------------------------------------------------------
  540. #pragma segment HeapSeg
  541.  
  542. MemoryHeap *MemoryHeap::GetNextHeap() const
  543. {
  544.     return fNextHeap;
  545. }
  546.  
  547. //----------------------------------------------------------------------------------------
  548. // MemoryHeap::GetZapOnAllocate
  549. //----------------------------------------------------------------------------------------
  550. #pragma segment HeapSeg
  551.  
  552. Boolean MemoryHeap::GetZapOnAllocate() const
  553. {
  554.     this->ValidateMagicNumber();
  555.  
  556.     return fZapOnAllocate;
  557. }
  558.  
  559. //----------------------------------------------------------------------------------------
  560. // MemoryHeap::GetZapOnFree
  561. //----------------------------------------------------------------------------------------
  562. #pragma segment HeapSeg
  563.  
  564. Boolean MemoryHeap::GetZapOnFree() const
  565. {
  566.     this->ValidateMagicNumber();
  567.  
  568.     return fZapOnFree;
  569. }
  570.  
  571. #if MM_DEBUG
  572. //----------------------------------------------------------------------------------------
  573. // MemoryHeap::AdoptHook (MM_DEBUG only)
  574. //----------------------------------------------------------------------------------------
  575. #pragma segment HeapSeg
  576.  
  577. void MemoryHeap::AdoptHook(ODMemoryHook *memoryHook)
  578. {
  579.     this->ValidateMagicNumber();
  580.  
  581.     fMemoryHookList.Add(memoryHook);
  582. }
  583. #endif
  584.  
  585. #if MM_DEBUG
  586. //----------------------------------------------------------------------------------------
  587. // MemoryHeap::IsValidBlock (MM_DEBUG only)
  588. //----------------------------------------------------------------------------------------
  589. #pragma segment HeapSeg
  590.  
  591. Boolean MemoryHeap::IsValidBlock(const void *blk) const
  592. {
  593.     this->ValidateMagicNumber();
  594.  
  595.     if (blk == NULL)
  596.         return false;
  597.     
  598.     blk = this->CallAboutToBlockSizeHooks(blk);
  599.         
  600.     if (this->IsMyBlock(blk))
  601.         return DoIsValidBlock(blk);
  602.     else
  603.         return false;
  604. }
  605. #endif
  606.  
  607. #if MM_DEBUG
  608. //----------------------------------------------------------------------------------------
  609. // MemoryHeap::FindBlockContaining (MM_DEBUG only)
  610. //----------------------------------------------------------------------------------------
  611. #pragma segment HeapSeg
  612.  
  613. MMBoolean MemoryHeap::FindBlockContaining( const void *start, const void *end,
  614.                                             const void* &blockStart, const void* &blockEnd ) const
  615. {
  616.     this->ValidateMagicNumber();
  617.  
  618.     if( ! this->DoFindBlockContaining(start,end, blockStart,blockEnd) )
  619.         return kMMFalse;
  620.     else {
  621.         if( blockStart ) {
  622.             ODBlockSize hdrSize = this->CallGetHeaderSize();
  623.             blockStart = (char*)blockStart + hdrSize;
  624.             blockEnd   = (char*)blockEnd - (this->CallAboutToAllocateHooks(0) - hdrSize);
  625.         }
  626.         return kMMTrue;
  627.     }
  628. }
  629. #endif
  630.  
  631. //----------------------------------------------------------------------------------------
  632. // MemoryHeap::NumberAllocatedBlocks
  633. //----------------------------------------------------------------------------------------
  634. #pragma segment HeapSeg
  635.  
  636. unsigned long MemoryHeap::NumberAllocatedBlocks() const
  637. {
  638.     this->ValidateMagicNumber();
  639.  
  640.     return fNumberAllocatedBlocks;
  641. }
  642.  
  643. //----------------------------------------------------------------------------------------
  644. // MemoryHeap::SetBlockIsObject
  645. //----------------------------------------------------------------------------------------
  646. void MemoryHeap::SetBlockIsObject( void* ptr, Boolean isObject )
  647. {
  648.     this->ValidateMagicNumber();
  649. #if MM_DEBUG
  650.     ptr = (void*) CallAboutToBlockSizeHooks(ptr);
  651. #endif
  652.     this->DoSetBlockIsObject(ptr,isObject );
  653. }
  654.  
  655. //----------------------------------------------------------------------------------------
  656. // MemoryHeap::BlockIsObject
  657. //----------------------------------------------------------------------------------------
  658. Boolean MemoryHeap::BlockIsObject( const void* ptr ) const
  659. {
  660.     this->ValidateMagicNumber();
  661. #if MM_DEBUG
  662.     ptr = CallAboutToBlockSizeHooks(ptr);
  663. #endif
  664.     return this->DoBlockIsObject(ptr);
  665. }
  666.  
  667. #if MM_DEBUG
  668. //----------------------------------------------------------------------------------------
  669. // MemoryHeap::SetBlockStackCrawl
  670. //----------------------------------------------------------------------------------------
  671. void MemoryHeap::SetBlockStackCrawl( const void* blk, StackCrawl *s )
  672. {
  673.     this->ValidateMagicNumber();
  674.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  675.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  676.         blk = hook->AboutToBlockSize(blk);
  677.         if( hook->GetType() == CBlockStackCrawlHook::kBlockStackCrawlHookType ) {
  678.             ((CBlockStackCrawlHook*)hook)->SetStackCrawl(blk,s);
  679.             return;
  680.         }
  681.     }
  682.     MM_WARN("No BlockStackCrawlHook for SetBlockStackCrawl");
  683. }
  684.  
  685. //----------------------------------------------------------------------------------------
  686. // MemoryHeap::GetBlockStackCrawl
  687. //----------------------------------------------------------------------------------------
  688. StackCrawl* MemoryHeap::GetBlockStackCrawl( const void* blk ) const
  689. {
  690.     this->ValidateMagicNumber();
  691.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  692.             hook != NULL; hook = fMemoryHookList.Before(hook)) {
  693.         blk = hook->AboutToBlockSize(blk);
  694.         if( hook->GetType() == CBlockStackCrawlHook::kBlockStackCrawlHookType ) {
  695.             return ((CBlockStackCrawlHook*)hook)->GetStackCrawl(blk);
  696.         }
  697.     }
  698.     MM_WARN("No BlockStackCrawlHook for GetBlockStackCrawl");
  699.     return NULL;
  700. }
  701. #endif
  702.  
  703. //----------------------------------------------------------------------------------------
  704. // MemoryHeap::GetBlockHeap
  705. //----------------------------------------------------------------------------------------
  706. MemoryHeap* MemoryHeap::GetBlockHeap( const void* ptr ) const
  707. {
  708.     // This makes the assumption (in a debug build) that the block's heap
  709.     // has the same memory hooks installed as this one. In reality this is the
  710.     // case; but at some future point it might cause trouble......
  711.     // In any case this will not occur in a non-debug build.
  712.     
  713.     this->ValidateMagicNumber();
  714. #if MM_DEBUG
  715.     ptr = this->CallAboutToBlockSizeHooks(ptr);
  716. #endif
  717.     return this->DoGetBlockHeap(ptr);
  718. }
  719.  
  720. //----------------------------------------------------------------------------------------
  721. // MemoryHeap::Reallocate
  722. //----------------------------------------------------------------------------------------
  723. #pragma segment HeapSeg
  724.  
  725. void *MemoryHeap::Reallocate(void *blk, ODBlockSize newSize)
  726. {
  727.     this->ValidateMagicNumber();
  728.  
  729.     if (blk == NULL)
  730.         return this->Allocate(newSize);
  731.         
  732.     ODBlockSize allocatedSize;
  733.     ODBlockSize oldBlkSize = (ODBlockSize) this->BlockSize(blk);
  734.     
  735. #if MM_DEBUG
  736.     void *oldBlk = blk;
  737.     this->CallAboutToReallocHooks(blk, newSize);
  738. #endif
  739.     
  740.     blk = this->DoReallocate(blk, newSize, allocatedSize);
  741.     
  742.     if (blk != NULL)
  743.         fBytesAllocated += allocatedSize - oldBlkSize;
  744.             
  745. #if MM_DEBUG
  746.     blk = this->CallDidReallocHooks(oldBlk,blk, newSize);
  747. #endif
  748.  
  749.     return blk;
  750. }
  751.  
  752.  
  753. //----------------------------------------------------------------------------------------
  754. // MemoryHeap::AllocateSlushFund
  755. //----------------------------------------------------------------------------------------
  756. #pragma segment HeapSeg
  757. MMBoolean MemoryHeap::AllocateSlushFund( size_t size, size_t allocSizeLimit )
  758. {
  759.     if( size==0 ) {
  760.         this->FreeSlushFund();
  761.         return kMMTrue;
  762.     }
  763.     this->Free(fSlushFund);
  764.     size_t oldLimit = fSlushFundAllocSizeLimit;
  765.     fSlushFundAllocSizeLimit = 0;
  766.     MMBlock slushy = this->Allocate(size);
  767.     if( !slushy ) {
  768.         if( fSlushFund ) {
  769.             fSlushFund = this->Allocate(fSlushFundSize);
  770.             if( !fSlushFund ) 
  771.                 MM_WARN("Yow! Lost slush fund accidentally");
  772.         }
  773.         return kMMFalse;
  774.     }
  775.     fSlushFund = slushy;
  776.     fSlushFundSize = size;
  777.     fSlushFundAllocSizeLimit = allocSizeLimit;
  778.     return kMMTrue;
  779. }
  780.  
  781. //----------------------------------------------------------------------------------------
  782. // MemoryHeap::FreeSlushFund
  783. //----------------------------------------------------------------------------------------
  784. #pragma segment HeapSeg
  785. size_t MemoryHeap::FreeSlushFund( )
  786. {
  787.     this->Free(fSlushFund);
  788.     fSlushFund = kMMNULL;
  789.     size_t size = fSlushFundSize;
  790.     fSlushFundSize = fSlushFundAllocSizeLimit = 0;
  791.     return size;
  792. }
  793.  
  794. #if MM_DEBUG
  795. //----------------------------------------------------------------------------------------
  796. // MemoryHeap::DeleteHook (MM_DEBUG only)
  797. //----------------------------------------------------------------------------------------
  798. #pragma segment HeapSeg
  799.  
  800. void MemoryHeap::DeleteHook(ODMemoryHook *memoryHook)
  801. {
  802.     this->ValidateMagicNumber();
  803.  
  804.     fMemoryHookList.Remove(memoryHook);
  805. }
  806. #endif
  807.  
  808. //----------------------------------------------------------------------------------------
  809. // MemoryHeap::Reset
  810. //----------------------------------------------------------------------------------------
  811. #pragma segment HeapSeg
  812.  
  813. void MemoryHeap::Reset()
  814. {
  815.     this->ValidateMagicNumber();
  816.  
  817. #if MM_DEBUG
  818.     this->CallAboutToResetHooks();
  819. #endif
  820.     
  821.     fBytesAllocated = 0;
  822.     fNumberAllocatedBlocks = 0;
  823.     
  824.     this->DoReset();
  825. }
  826.  
  827. #if MM_DEBUG
  828. //----------------------------------------------------------------------------------------
  829. // MemoryHeap::SetAutoValidation (MM_DEBUG only)
  830. //----------------------------------------------------------------------------------------
  831. #pragma segment HeapSeg
  832.  
  833. void MemoryHeap::SetAutoValidation(Boolean autoValidation)
  834. {
  835.     this->ValidateMagicNumber();
  836.  
  837.     fAutoValidation = autoValidation;
  838. }
  839. #endif
  840.  
  841. //----------------------------------------------------------------------------------------
  842. // MemoryHeap::SetDescription
  843. //----------------------------------------------------------------------------------------
  844. #pragma segment HeapSeg
  845.  
  846. void MemoryHeap::SetDescription(const char *description)
  847. {
  848.     this->ValidateMagicNumber();
  849.  
  850.     // ------ Set the description without depending on other code
  851.     
  852.     const char *src = description;
  853.     char *dst = fDescription;
  854.     int i;
  855.     
  856.     for (i = 0; i < kDescriptionLength - 1 && *src; i++)
  857.         *dst++ = *src++;
  858.     fDescription[i] = 0;
  859. }
  860.  
  861. //----------------------------------------------------------------------------------------
  862. // MemoryHeap::SetZapOnAllocate
  863. //----------------------------------------------------------------------------------------
  864. #pragma segment HeapSeg
  865.  
  866. void MemoryHeap::SetZapOnAllocate(Boolean zapOnAllocate)
  867. {
  868.     this->ValidateMagicNumber();
  869.  
  870.     fZapOnAllocate = zapOnAllocate;
  871. }
  872.  
  873. //----------------------------------------------------------------------------------------
  874. // MemoryHeap::SetZapOnFree
  875. //----------------------------------------------------------------------------------------
  876. #pragma segment HeapSeg
  877.  
  878. void MemoryHeap::SetZapOnFree(Boolean zapOnFree)
  879. {
  880.     this->ValidateMagicNumber();
  881.  
  882.     fZapOnFree = zapOnFree;
  883. }
  884.  
  885. //----------------------------------------------------------------------------------------
  886. // MemoryHeap::~MemoryHeap
  887. //----------------------------------------------------------------------------------------
  888. #pragma segment HeapSeg
  889.  
  890. MemoryHeap::~MemoryHeap()
  891. {
  892.     this->ValidateMagicNumber();
  893.  
  894.     // ----- Remove from the static list of heaps
  895.     
  896.     MemoryHeap *lastHeap = NULL, *currentHeap = fHeapList;
  897.     
  898.     while (currentHeap != NULL)
  899.     {
  900.         if (this == currentHeap)
  901.         {
  902.             if (lastHeap == NULL)
  903.                 fHeapList = currentHeap->GetNextHeap();
  904.             else
  905.                 lastHeap->fNextHeap = currentHeap->GetNextHeap();
  906.             
  907.             currentHeap = NULL;
  908.         }
  909.         else
  910.         {
  911.             lastHeap = currentHeap;
  912.             currentHeap = currentHeap->GetNextHeap();
  913.         }
  914.     }
  915.  
  916.     // ------ Set the default description without depending on other code
  917.     
  918.     const char *src = kDeadHeapDescription;
  919.     char *dst = fDescription;    
  920.     for (; *src;)
  921.         *dst++ = *src++;
  922.     *dst = 0;
  923.     
  924.     fMagicNumber = 0;
  925. }
  926.  
  927. //----------------------------------------------------------------------------------------
  928. // MemoryHeap::MemoryHeap
  929. //----------------------------------------------------------------------------------------
  930. #pragma segment HeapSeg
  931.  
  932. MemoryHeap::MemoryHeap(Boolean autoValidation,
  933.                        Boolean zapOnAllocate,
  934.                        Boolean zapOnFree,
  935.                        MMHeapLocation memSrc) :
  936.     fAutoValidation(autoValidation),
  937.     fZapOnAllocate(zapOnAllocate),
  938.     fZapOnFree(zapOnFree),
  939.     fBytesAllocated(0),
  940.     fNumberAllocatedBlocks(0),
  941.     fMemSource(memSrc),
  942.     fMagicNumber(kMagicNumber),
  943.     fSlushFund(kMMNULL),
  944.     fSlushFundSize(0),
  945.     fSlushFundAllocSizeLimit(0)
  946. {
  947.     // ------ Set the default description without depending on other code
  948.     
  949.     const char *src = kDefaultDescription;
  950.     char *dst = fDescription;    
  951.     for (; *src;)
  952.         *dst++ = *src++;
  953.     *dst = 0;
  954.     
  955.     // Add to the static list of heaps
  956.     
  957.     fNextHeap = fHeapList;
  958.     fHeapList = this;
  959. }
  960.  
  961. //----------------------------------------------------------------------------------------
  962. // MemoryHeap::operator new
  963. //----------------------------------------------------------------------------------------
  964. #pragma segment HeapSeg
  965.  
  966. void* MemoryHeap::operator new(size_t size, MMHeapLocation src)
  967. {
  968.     return PlatformAllocateBlock(size, src);
  969. }
  970.  
  971. //----------------------------------------------------------------------------------------
  972. // MemoryHeap::operator delete
  973. //----------------------------------------------------------------------------------------
  974. #pragma segment HeapSeg
  975.  
  976. void MemoryHeap::operator delete(void* ptr)
  977. {
  978.         PlatformFreeBlock(ptr);
  979. }
  980.  
  981. //----------------------------------------------------------------------------------------
  982. // MemoryHeap::AllocateRawMemory
  983. //----------------------------------------------------------------------------------------
  984. #pragma segment HeapSeg
  985.  
  986. void *MemoryHeap::AllocateRawMemory(ODBlockSize size)
  987. {
  988.     return PlatformAllocateBlock(size, fMemSource);
  989. }
  990.  
  991. //----------------------------------------------------------------------------------------
  992. // MemoryHeap::DoReallocate
  993. //----------------------------------------------------------------------------------------
  994. #pragma segment HeapSeg
  995.  
  996. void *MemoryHeap::DoReallocate(void *block, ODBlockSize newSize, ODBlockSize &allocatedSize)
  997. {
  998.     ODBlockSize oldRealSize = this->DoBlockSize(block);
  999.     void* newBlock = this->DoAllocate(newSize, allocatedSize);
  1000.     
  1001.     if (newBlock != NULL)
  1002.     {
  1003.         ODBlockSize copySize = newSize <= oldRealSize ? newSize : oldRealSize;
  1004.         PlatformCopyMemory(block, newBlock, copySize);
  1005.  
  1006.         if (fZapOnFree)
  1007.         {
  1008.             char *chrBlk = (char *) block;
  1009.             for (ODBlockSize i = 0; i < oldRealSize; i++)
  1010.                 *chrBlk++ = 0xDD;
  1011.         }
  1012.  
  1013.         this->DoFree(block);
  1014.     }
  1015.     else
  1016.       if (newSize <= oldRealSize)   //if unable to get new fMem, and newSize is <= real size
  1017.         return block;               //then return original ptr unchanged
  1018.  
  1019.     return newBlock;
  1020. }
  1021.         
  1022. //----------------------------------------------------------------------------------------
  1023. // MemoryHeap::FreeRawMemory
  1024. //----------------------------------------------------------------------------------------
  1025. #pragma segment HeapSeg
  1026.  
  1027. void MemoryHeap::FreeRawMemory(void* ptr)
  1028. {
  1029.     PlatformFreeBlock(ptr);
  1030. }
  1031.  
  1032. #if MM_DEBUG
  1033. //----------------------------------------------------------------------------------------
  1034. // MemoryHeap::CompilerCheck (MM_DEBUG only)
  1035. //----------------------------------------------------------------------------------------
  1036. #pragma segment HeapSeg
  1037.  
  1038. void MemoryHeap::CompilerCheck()
  1039. {
  1040. }
  1041. #endif
  1042.  
  1043. #if MM_DEBUG
  1044. //----------------------------------------------------------------------------------------
  1045. // MemoryHeap::CallAboutToAllocateHooks (MM_DEBUG only)
  1046. //----------------------------------------------------------------------------------------
  1047. #pragma segment HeapSeg
  1048.  
  1049. ODBlockSize MemoryHeap::CallAboutToAllocateHooks(ODBlockSize size) const
  1050. {
  1051.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1052.             hook != NULL; hook = fMemoryHookList.After(hook))
  1053.         size = hook->AboutToAllocate(size);
  1054.         
  1055.     return size;
  1056. }
  1057. #endif
  1058.  
  1059. #if MM_DEBUG
  1060. //----------------------------------------------------------------------------------------
  1061. // MemoryHeap::CallGetHeaderSize (MM_DEBUG only)
  1062. //----------------------------------------------------------------------------------------
  1063. #pragma segment HeapSeg
  1064.  
  1065. ODBlockSize MemoryHeap::CallGetHeaderSize() const
  1066. {
  1067.     ODBlockSize size = 0;
  1068.     
  1069.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1070.             hook != NULL; hook = fMemoryHookList.After(hook))
  1071.         size += hook->GetHeaderSize();
  1072.         
  1073.     return size;
  1074. }
  1075. #endif
  1076.  
  1077. #if MM_DEBUG
  1078. //----------------------------------------------------------------------------------------
  1079. // MemoryHeap::CallDidAllocateHooks (MM_DEBUG only)
  1080. //----------------------------------------------------------------------------------------
  1081. #pragma segment HeapSeg
  1082.  
  1083. void *MemoryHeap::CallDidAllocateHooks(void* blk, ODBlockSize size)
  1084. {
  1085.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1086.             hook != NULL; hook = fMemoryHookList.After(hook)) {
  1087.         blk = hook->DidAllocate(blk, size);
  1088.         size -= hook->AboutToAllocate(0);
  1089.     }
  1090.     return blk;
  1091. }
  1092. #endif
  1093.  
  1094. #if MM_DEBUG
  1095. //----------------------------------------------------------------------------------------
  1096. // MemoryHeap::CallAboutToBlockSizeHooks (MM_DEBUG only)
  1097. //----------------------------------------------------------------------------------------
  1098. #pragma segment HeapSeg
  1099.  
  1100. const void *MemoryHeap::CallAboutToBlockSizeHooks(const void* blk) const
  1101. {
  1102.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  1103.             hook != NULL; hook = fMemoryHookList.Before(hook))
  1104.         blk = hook->AboutToBlockSize(blk);
  1105.         
  1106.     return (void*) blk;
  1107. }
  1108. #endif
  1109.  
  1110. #if MM_DEBUG
  1111. //----------------------------------------------------------------------------------------
  1112. // MemoryHeap::CallAboutToFreeHooks (MM_DEBUG only)
  1113. //----------------------------------------------------------------------------------------
  1114. #pragma segment HeapSeg
  1115.  
  1116. void *MemoryHeap::CallAboutToFreeHooks(void* blk)
  1117. {
  1118.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  1119.             hook != NULL; hook = fMemoryHookList.Before(hook))
  1120.         blk = hook->AboutToFree(blk);
  1121.         
  1122.     return blk;
  1123. }
  1124. #endif
  1125.  
  1126. #if MM_DEBUG
  1127. //----------------------------------------------------------------------------------------
  1128. // MemoryHeap::CallAboutToReallocHooks (MM_DEBUG only)
  1129. //----------------------------------------------------------------------------------------
  1130. #pragma segment HeapSeg
  1131.  
  1132. void MemoryHeap::CallAboutToReallocHooks(void* &blk, ODBlockSize& size)
  1133. {
  1134.     for (ODMemoryHook *hook = fMemoryHookList.Last();
  1135.             hook != NULL; hook = fMemoryHookList.Before(hook))
  1136.         hook->AboutToRealloc(blk, size);
  1137. }
  1138. #endif
  1139.  
  1140. #if MM_DEBUG
  1141. //----------------------------------------------------------------------------------------
  1142. // MemoryHeap::CallDidReallocHooks (MM_DEBUG only)
  1143. //----------------------------------------------------------------------------------------
  1144. #pragma segment HeapSeg
  1145.  
  1146. void *MemoryHeap::CallDidReallocHooks(void *oldBlk, void *blk, ODBlockSize size)
  1147. {
  1148.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1149.             hook != NULL; hook = fMemoryHookList.After(hook)) {
  1150.         blk = hook->DidRealloc(oldBlk, blk, size);
  1151.         size -= hook->AboutToAllocate(0);
  1152.     }
  1153.     return blk;
  1154. }
  1155. #endif
  1156.  
  1157. #if MM_DEBUG
  1158. //----------------------------------------------------------------------------------------
  1159. // MemoryHeap::CallAboutToResetHooks (MM_DEBUG only)
  1160. //----------------------------------------------------------------------------------------
  1161. #pragma segment HeapSeg
  1162.  
  1163. void MemoryHeap::CallAboutToResetHooks()
  1164. {
  1165.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1166.             hook != NULL; hook = fMemoryHookList.After(hook))
  1167.         hook->AboutToReset();
  1168. }
  1169. #endif
  1170.  
  1171. #if MM_DEBUG
  1172. //----------------------------------------------------------------------------------------
  1173. // MemoryHeap::CallCommentHooks (MM_DEBUG only)
  1174. //----------------------------------------------------------------------------------------
  1175. #pragma segment HeapSeg
  1176.  
  1177. void MemoryHeap::CallCommentHooks(const char* comment)
  1178. {
  1179.     for (ODMemoryHook *hook = fMemoryHookList.First();
  1180.             hook != NULL; hook = fMemoryHookList.After(hook))
  1181.         hook->Comment(comment);
  1182. }
  1183. #endif
  1184.  
  1185. #if MM_DEBUG
  1186. //----------------------------------------------------------------------------------------
  1187. // MemoryHeap::ValidateAndReport (MM_DEBUG only)
  1188. //----------------------------------------------------------------------------------------
  1189. #pragma segment HeapSeg
  1190.  
  1191. void MemoryHeap::ValidateAndReport(void *blk) const
  1192. {
  1193.     MM_ASSERT(this->IsValidBlock(blk));
  1194. }
  1195. #endif
  1196.